#include "shmipc/core/shm_cond.h"

#include <errno.h>
#include <string.h>
#include <stdio.h>

namespace shmipc::core {


ShmCond::ShmCond() {
    pthread_condattr_t  attr;
    pthread_condattr_init(&attr);
    pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
    //pthread_condattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
    pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
    pthread_cond_init(&cond_, &attr);
    pthread_condattr_destroy(&attr);
}

ShmCond::~ShmCond() {
    pthread_cond_destroy(&cond_);
}

void ShmCond::wait(AutoShmMutex& lock) {
    pthread_cond_wait(&cond_, &lock.lock_.mutex_);
}

shm_cond_status ShmCond::wait_for(AutoShmMutex& lock, uint32_t timeout_ms) {
    timespec tm;
    clock_gettime(CLOCK_MONOTONIC, &tm);

    tm.tv_sec += timeout_ms / 1000;
    tm.tv_nsec = (timeout_ms % 1000) * 1000000;
    int ret = pthread_cond_timedwait(&cond_, &lock.lock_.mutex_, &tm);
    if (ret == 0) { 
        return shm_cond_status::Ready; 
    } else if (ret == ETIMEDOUT) {
        return shm_cond_status::Timeout;
    }
    return shm_cond_status::Error;
}

void ShmCond::notify_one() {
    pthread_cond_signal(&cond_);
}

void ShmCond::notify_all() {
    pthread_cond_broadcast(&cond_);
}

} //namespace shmipc::core